﻿using System;
using System.Collections.Generic;
using System.Management;
using System.Threading;
using ClusterAwareProperties;
using ClusterAwareWMI;

namespace ClusterAware
{
    /// <summary>
    /// Enum Refresh Option
    /// </summary>
    public enum RefreshOption
    {
        /// <summary>
        /// Refresh all instances
        /// </summary>
        All,
        /// <summary>
        /// Refresh Group instances 
        /// </summary>
        Groups,
        /// <summary>
        /// Refresh Resource instances
        /// </summary>
        Resources,
        /// <summary>
        /// Refresh ResourceType instances
        /// </summary>
        ResourceTypes,
        /// <summary>
        /// Resfresh Node instances
        /// </summary>
        Nodes,
        /// <summary>
        /// Refresh Network instances
        /// </summary>
        Networks,
        /// <summary>
        /// Refresh NetworkInterface instances
        /// </summary>
        NetworkInterface
    }


    ///<summary>
    /// Event Handler Resource State Change
    ///</summary>
    ///<param name="sender">ClusterManager Instance</param>
    ///<param name="ev">EventResourceStateChangeProperties Class</param>
    public delegate void ResourceStateChangeEventHandler(object sender, EventResourceStateChangePropety ev);


    /// <summary>
    /// Cluster Manager Class
    /// </summary>
    public class ClusterManager : IDisposable
    {

        #region Events

        /// <summary>
        /// Event Resource State Change
        /// </summary>
        public event ResourceStateChangeEventHandler ResourceStateChange;

        /// <summary>
        /// Event Group State Change
        /// </summary>
        public event ResourceStateChangeEventHandler GroupStateChange;

        /// <summary>
        /// Event Cluster Object Add
        /// </summary>
        public event ResourceStateChangeEventHandler ClusterObjectAdd;

        /// <summary>
        /// Event Cluster Object Remove
        /// </summary>
        public event ResourceStateChangeEventHandler ClusterObjectRemove;

        #endregion

        #region Constructor

        /// <summary>
        /// Constructor
        /// </summary>
        public ClusterManager()
        {
            Scope = "root\\MSCluster";
            Machine = Environment.MachineName;
            Authentication = AuthenticationLevel.PacketPrivacy;
            OperationSystem = WindowsOperationSystem.Unknown;
            ManagerInstance = this;

            _resourceMethods = new ResourceMethods(this);
            _resourceMethods = new ResourceMethods(this);
            _groupMethods = new GroupMethods(this);
            _nodeMethods = new NodeMethods(this);
            _resourceTypeMethods = new ResourceTypeMethods(this);
            _networkMethods = new NetworkMethods(this);
            _networkInterfaceMethods = new NetworkInterfaceMethods(this);
        }

        #endregion

        #region private fields

        private string _machine;
        private bool _cacheInstances;

        private Thread _threadResourceStateChange;
        private bool _abortThreadResourceStateChange;

        private Thread _threadGroupStateChange;
        private bool _abortThreadGroupStateChange;

        private Thread _threadObjectAdd;
        private bool _abortThreadObjectAdd;


        private Thread _threadClusterObjectRemove;
        private bool _abortThreadObjectRemove;

        private readonly ResourceMethods _resourceMethods;
        private readonly GroupMethods _groupMethods;
        private readonly NodeMethods _nodeMethods;
        private readonly ResourceTypeMethods _resourceTypeMethods;
        private readonly NetworkMethods _networkMethods;
        private readonly NetworkInterfaceMethods _networkInterfaceMethods;

        #endregion

        #region internal fields

        internal Dictionary<string, GroupProperty> GroupInstances;
        internal Dictionary<string, ResourceProperty> ResourceInstances;
        internal Dictionary<string, NodeProperty> NodeInstances;
        internal Dictionary<string, ResourceTypeProperty> ResourceTypeInstances;
        internal Dictionary<string, NetworkProperty> NetworkInstances;
        internal Dictionary<string, NetworkInterfaceProperty> NetworkInterfaceInstances;
        internal ManagementScope ScopeManager;
        internal ClusterManager ManagerInstance;

        #endregion

        #region Public Properties

        /// <summary>
        /// If true ClusterManager is connected in scope Cluster WMI. 
        /// </summary>
        public bool IsConnected { get; internal set; }

        /// <summary>
        /// Scope WMI
        /// </summary>
        /// <remarks>
        /// Default vale :  "root\\MSCluster"
        /// </remarks>
        public string Scope { get; internal set; }

        /// <summary>
        /// Domain where cluster is running
        /// </summary>
        /// <remarks>
        /// Default valyue : Environment.UserDomainName
        /// </remarks>
        public string Domain { get; set; }

        /// <summary>
        /// Machine Name or Custer name
        /// </summary>
        /// <remarks>
        /// Default value :  Environment.MachineName
        /// </remarks>
        public string Machine
        {
            get { return _machine; }
            set
            {
                _machine = value;
                if (_machine == Environment.MachineName)
                {
                    Scope = "root\\MSCluster";
                }
                else
                {
                    Scope = "\\\\" + Machine + "\\root\\MSCluster";
                }

            }
        }

        /// <summary>
        /// Windows Operation System where cluster is running
        /// </summary>
        /// <remarks>
        /// Default value : WindowsOperationSystem.Unknown;
        /// </remarks>
        public WindowsOperationSystem OperationSystem { get; internal set; }

        /// <summary>
        /// Username to connect
        /// </summary>
        /// <remarks>
        /// Default value : Environment.UserName
        /// </remarks>
        public string Username { get; set; }

        /// <summary>
        /// Password to connect
        /// </summary>
        public string Password { get; set; }

        /// <summary>
        /// Authentication mode
        /// </summary>
        /// <remarks>
        /// Default value : AuthenticationLevel.PacketPrivacy
        /// </remarks>
        public AuthenticationLevel Authentication { get; set; }

        /// <summary>
        /// Cache Instances local.
        /// IF true the instances only update when execute methods
        /// if false thes instances always update 
        /// Default value : false;
        /// </summary>
        public bool CacheInstances
        {
            get { return _cacheInstances; }
            set
            {
                if (!IsConnected)
                {
                    _cacheInstances = value;
                }
                else
                {
                    if (_cacheInstances != value)
                    {
                        _cacheInstances = value;
                        Connect();
                    }
                    else
                    {
                        _cacheInstances = value;
                    }
                }
            }
        }

        /// <summary>
        /// Resource Group methods and properties
        /// </summary>
        public GroupMethods Groups
        {
            get { return _groupMethods; }
        }

        /// <summary>
        /// Resource methods and properties
        /// </summary>
        public ResourceMethods Resources
        {
            get { return _resourceMethods; }
        }

        /// <summary>
        /// Node methods and properties
        /// </summary>
        public NodeMethods Nodes
        {
            get { return _nodeMethods; }
        }

        /// <summary>
        /// Resourcetypes methods and properties
        /// </summary>
        public ResourceTypeMethods ResourceTypes
        {
            get { return _resourceTypeMethods; }
        }

        /// <summary>
        /// Network methods and properties
        /// </summary>
        public NetworkMethods Networks
        {
            get { return _networkMethods; }
        }

        /// <summary>
        /// NetworksInterface methods and properties
        /// </summary>
        public NetworkInterfaceMethods NetworksInterfaces
        {
            get { return _networkInterfaceMethods; }
        }

        #endregion

        #region public Methods


        ///<summary>
        /// Disconnected Cluster
        ///</summary>
        ///<exception cref="ClusterManagerException">
        /// this method throws exception for the following conditions:
        /// Failed WMI method execution
        /// </exception>
        public void Disconnect()
        {
            //cancel thread cluster Object Remome
            DisabledWatcherClusterObjectRemove(500);

            //cancel thread cluster Object add
            DisabledWatcherClusterObjectAdd(500);

            //cancel thread Group State Change
            DisabledWatcherGroupStateChange(500);

            //cancel thread Resource State Change
            DisabledWatcherResourceStateChange(500);

            //dispose internal objects;
            DisposeManagementObjects();

            //clear references
            GroupInstances = null;
            ResourceInstances = null;
            NodeInstances = null;
            NodeInstances = null;
            NetworkInstances = null;
            NetworkInterfaceInstances = null;
            ScopeManager = null;
            IsConnected = false;
        }

        /// <summary>
        /// Cluster Connect and persist ManagementScope
        /// </summary>
        ///<exception cref="ClusterManagerException">
        /// this method throws exception for the following conditions:
        /// Failed WMI method execution
        /// </exception>
        public void Connect()
        {
            IsConnected = false;
            var ch = new ClusterWmiHelpper();
            try
            {
                ScopeManager = ch.GetScope(Scope, Domain, Machine, Username, Password, Authentication);
                IsConnected = true;
            }
            catch (ManagementException ex)
            {
                throw new ClusterManagerException(Properties.Resources.Error_MethodConnect, ex);
            }
            catch (Exception ex)
            {
                throw new ClusterManagerException(Properties.Resources.Error_MethodConnect, ex);
            }

            DisabledWatcher();

            DisposeManagementObjects();

            #region ManagementObjects instances

            NetworkInstances = new Dictionary<string, NetworkProperty>();
            ResourceTypeInstances = new Dictionary<string, ResourceTypeProperty>();
            GroupInstances = new Dictionary<string, GroupProperty>();
            ResourceInstances = new Dictionary<string, ResourceProperty>();
            NodeInstances = new Dictionary<string, NodeProperty>();
            NetworkInterfaceInstances = new Dictionary<string, NetworkInterfaceProperty>();

            #endregion

            //Get Operation System running on Cluster
            OperationSystem = ch.GetOperationSystem(ScopeManager);

            if (!CacheInstances) return;

            //load networkinteface
            foreach (var net in ch.GetNetworkInterfaces(ScopeManager))
            {
                NetworkInterfaceInstances.Add(net.Name, net);
            }

            //load Network
            foreach (var net in ch.GetNetworks(ScopeManager))
            {
                NetworkInstances.Add(net.Name, net);
            }
            //load resourcetypes
            foreach (var res in ch.GetResourceTypes(ScopeManager))
            {
                ResourceTypeInstances.Add(res.Name, res);
            }
            //load groups
            foreach (var grp in ch.GetGroups(ScopeManager))
            {
                GroupInstances.Add(grp.Name, grp);
            }
            //load resources
            foreach (var res in ch.GetResources(ScopeManager))
            {
                ResourceInstances.Add(res.Name, res);
            }
            //load nodes and cluster properties
            foreach (var node in ch.GetNodes(ScopeManager))
            {
                NodeInstances.Add(node.Name, node);
            }


        }

        /// <summary>
        /// Refresh All informations
        /// </summary>
        ///<exception cref="ClusterManagerException">
        /// this method throws exception for the following conditions:
        /// Failed WMI method connect execution
        /// </exception>
        public void Refresh()
        {
            Refresh(RefreshOption.All, null);
        }


        /// <summary>
        /// Refresh specific feature informations
        /// </summary>
        /// <param name="options">Options to refresh</param>
        ///<exception cref="ClusterManagerException">
        /// this method throws exception for the following conditions:
        /// Failed WMI method execution for refresh option
        /// </exception>
        public void Refresh(RefreshOption options)
        {
            Refresh(options, null);
        }


        /// <summary>
        /// Refresh specific feature informations
        /// </summary>
        /// <param name="options">Options to refresh</param>
        ///<param name="nameObject">name object to refresh</param>
        ///<exception cref="ClusterManagerException">
        /// this method throws exception for the following conditions:
        /// Failed WMI method execution for refresh option
        /// </exception>
        public void Refresh(RefreshOption options, string nameObject)
        {
            if (!IsConnected)
            {
                throw new ClusterManagerException(Properties.Resources.Error_NotConnected);
            }

            switch (options)
            {
                case RefreshOption.All:
                    {
                        if (!CacheInstances) return;
                        Disconnect();
                        Connect();
                    }
                    break;
                case RefreshOption.Groups:
                    {
                        if (!CacheInstances) return;
                        var ch = new ClusterWmiHelpper();
                        if (nameObject != null)
                        {
                            if (GroupInstances.ContainsKey(nameObject))
                            {
                                GroupInstances[nameObject] = ch.GetGroup(nameObject, ScopeManager);
                            }
                            else
                            {
                                GroupInstances.Add(nameObject, ch.GetGroup(nameObject, ScopeManager));
                            }
                        }
                        else
                        {
                            GroupInstances = new Dictionary<string, GroupProperty>();
                            foreach (var grp in ch.GetGroups(ScopeManager))
                            {
                                GroupInstances.Add(grp.Name, grp);
                            }
                        }
                    }
                    break;
                case RefreshOption.Resources:
                    {
                        if (!CacheInstances) return;
                        var ch = new ClusterWmiHelpper();
                        if (nameObject != null)
                        {
                            if (ResourceInstances.ContainsKey(nameObject))
                            {
                                ResourceInstances[nameObject] = ch.GetResource(nameObject, ScopeManager);
                            }
                            else
                            {
                                ResourceInstances.Add(nameObject, ch.GetResource(nameObject, ScopeManager));
                            }
                        }
                        else
                        {

                            ResourceInstances = new Dictionary<string, ResourceProperty>();
                            foreach (var res in ch.GetResources(ScopeManager))
                            {
                                ResourceInstances.Add(res.Name, res);
                            }
                        }
                    }
                    break;
                case RefreshOption.Nodes:
                    {
                        if (!CacheInstances) return;
                        var ch = new ClusterWmiHelpper();
                        if (nameObject != null)
                        {
                            if (NodeInstances.ContainsKey(nameObject))
                            {
                                NodeInstances[nameObject] = ch.GetNode(nameObject, ScopeManager);
                            }
                            else
                            {
                                NodeInstances.Add(nameObject, ch.GetNode(nameObject, ScopeManager));
                            }
                        }
                        else
                        {
                            NodeInstances = new Dictionary<string, NodeProperty>();
                            foreach (var node in ch.GetNodes(ScopeManager))
                            {
                                NodeInstances.Add(node.Name, node);
                            }
                        }
                    }
                    break;
                case RefreshOption.ResourceTypes:
                    {
                        if (!CacheInstances) return;
                        var ch = new ClusterWmiHelpper();
                        if (nameObject != null)
                        {
                            if (ResourceTypeInstances.ContainsKey(nameObject))
                            {
                                ResourceTypeInstances[nameObject] = ch.GetResourceType(nameObject, ScopeManager);
                            }
                            else
                            {
                                ResourceTypeInstances.Add(nameObject, ch.GetResourceType(nameObject, ScopeManager));
                            }
                        }
                        else
                        {
                            ResourceTypeInstances = new Dictionary<string, ResourceTypeProperty>();
                            foreach (var res in ch.GetResourceTypes(ScopeManager))
                            {
                                ResourceTypeInstances.Add(res.Name, res);
                            }
                        }
                    }

                    break;
                case RefreshOption.Networks:
                    {
                        if (!CacheInstances) return;
                        var ch = new ClusterWmiHelpper();
                        if (nameObject != null)
                        {
                            if (NetworkInstances.ContainsKey(nameObject))
                            {
                                NetworkInstances[nameObject] = ch.GetNetwork(nameObject, ScopeManager);
                            }
                            else
                            {
                                NetworkInstances.Add(nameObject, ch.GetNetwork(nameObject, ScopeManager));
                            }
                        }
                        else
                        {
                            NetworkInstances = new Dictionary<string, NetworkProperty>();
                            foreach (var net in ch.GetNetworks(ScopeManager))
                            {
                                NetworkInstances.Add(net.Name, net);
                            }
                        }
                    }
                    break;
                case RefreshOption.NetworkInterface:
                    {
                        if (!CacheInstances) return;
                        var ch = new ClusterWmiHelpper();
                        if (nameObject != null)
                        {
                            if (NetworkInterfaceInstances.ContainsKey(nameObject))
                            {
                                NetworkInterfaceInstances[nameObject] = ch.GetNetworkInterface(nameObject, ScopeManager);
                            }
                            else
                            {
                                NetworkInterfaceInstances.Add(nameObject, ch.GetNetworkInterface(nameObject, ScopeManager));
                            }
                        }
                        else
                        {
                            NetworkInterfaceInstances = new Dictionary<string, NetworkInterfaceProperty>();
                            foreach (var net in ch.GetNetworkInterfaces(ScopeManager))
                            {
                                NetworkInterfaceInstances.Add(net.Name, net);
                            }
                        }
                    }
                    break;
            }
        }

        /// <summary>
        /// Disabled Watcher Resource State Change
        /// </summary>
        /// <param name="timeOutWatcher">timeoput (in milliseconds) to wait Aborted</param>
        public void DisabledWatcherResourceStateChange(int timeOutWatcher)
        {
            if (_threadResourceStateChange == null) return;
            _abortThreadResourceStateChange = true;
            while (_threadResourceStateChange.ThreadState != ThreadState.Stopped)
            {
                Thread.Sleep(100);
            }
            _threadResourceStateChange = null;
        }

        /// <summary>
        /// Enabled Watcher Resource State Change
        /// </summary>
        public void EnabledWatcherResourceStateChange()
        {
            if (_threadResourceStateChange != null)
            {
                DisabledWatcherResourceStateChange(500);
            }
            _abortThreadResourceStateChange = false;
            _threadResourceStateChange = new Thread(ThreadWatcherResourceStateChange);
            _threadResourceStateChange.Start();
        }

        /// <summary>
        /// Disabled Watcher Group State Change
        /// </summary>
        /// <param name="timeOutWatcher">timeoput (in milliseconds) to wait Aborted</param>
        public void DisabledWatcherGroupStateChange(int timeOutWatcher)
        {
            if (_threadGroupStateChange == null) return;
            _abortThreadGroupStateChange = true;
            while (_threadGroupStateChange.ThreadState != ThreadState.Stopped)
            {
                Thread.Sleep(100);
            }
            _threadGroupStateChange = null;
        }

        /// <summary>
        /// Enabled Watcher Group State Change
        /// </summary>
        public void EnabledWatcherGroupStateChange()
        {
            if (_threadGroupStateChange != null)
            {
                DisabledWatcherGroupStateChange(500);
            }
            _abortThreadGroupStateChange = false;
            _threadGroupStateChange = new Thread(ThreadWatcherGroupStateChange);
            _threadGroupStateChange.Start();
        }

        /// <summary>
        /// Disabled Watcher Cluster Object Add
        /// </summary>
        /// <param name="timeOutWatcher">timeoput (in milliseconds) to wait Aborted</param>
        public void DisabledWatcherClusterObjectAdd(int timeOutWatcher)
        {
            if (_threadObjectAdd == null) return;
            _abortThreadObjectAdd = true;
            while (_threadObjectAdd.ThreadState != ThreadState.Stopped)
            {
                Thread.Sleep(100);
            }
            _threadObjectAdd = null;
        }

        /// <summary>
        /// Enabled Watcher Group State Change
        /// </summary>
        public void EnabledWatcherClusterObjectAdd()
        {
            if (_threadObjectAdd != null)
            {
                DisabledWatcherClusterObjectAdd(500);
            }
            _abortThreadObjectAdd = false;
            _threadObjectAdd = new Thread(ThreadWatcherObjectAdd);
            _threadObjectAdd.Start();
        }

        /// <summary>
        /// Disabled Watcher Cluster Object Remove
        /// </summary>
        /// <param name="timeOutWatcher">timeoput (in milliseconds) to wait Aborted</param>
        public void DisabledWatcherClusterObjectRemove(int timeOutWatcher)
        {
            if (_threadClusterObjectRemove == null) return;
            _abortThreadObjectRemove = true;
            while (_threadClusterObjectRemove.ThreadState != ThreadState.Stopped)
            {
                Thread.Sleep(100);
            }
            _threadClusterObjectRemove = null;
        }

        /// <summary>
        /// Enabled Watcher Group State Change
        /// </summary>
        public void EnabledWatcherClusterObjectRemove()
        {
            if (_threadClusterObjectRemove != null)
            {
                DisabledWatcherClusterObjectRemove(500);
            }
            _abortThreadObjectRemove = false;
            _threadClusterObjectRemove = new Thread(ThreadWatcherObjectRemove);
            _threadClusterObjectRemove.Start();
        }


        /// <summary>
        /// Enabled Watcher Events
        /// </summary>
        public void EnabledWatcher()
        {
            EnabledWatcherClusterObjectAdd();
            EnabledWatcherClusterObjectRemove();
            EnabledWatcherGroupStateChange();
            EnabledWatcherResourceStateChange();
        }

        /// <summary>
        /// Disabled Watcher Events
        /// </summary>
        public void DisabledWatcher()
        {
            DisabledWatcherClusterObjectAdd(500);
            DisabledWatcherClusterObjectRemove(500);
            DisabledWatcherGroupStateChange(500);
            DisabledWatcherResourceStateChange(500);
        }


        #endregion

        #region private Methods

        private void DisposeManagementObjects()
        {
            if (GroupInstances != null)
            {
                foreach (var item in GroupInstances)
                {
                    item.Value.Instance.Dispose();
                }
            }
            if (ResourceInstances != null)
            {
                foreach (var item in ResourceInstances)
                {
                    item.Value.Instance.Dispose();
                }
            }
            if (NodeInstances != null)
            {
                foreach (var item in NodeInstances)
                {
                    item.Value.Instance.Dispose();
                }
            }
            if (ResourceTypeInstances != null)
            {
                foreach (var item in ResourceTypeInstances)
                {
                    item.Value.Instance.Dispose();
                }
            }
            if (NetworkInstances != null)
            {
                foreach (var item in NetworkInstances)
                {
                    item.Value.Instance.Dispose();
                }
            }
            if (NetworkInterfaceInstances != null)
            {
                foreach (var item in NetworkInterfaceInstances)
                {
                    item.Value.Instance.Dispose();
                }
            }
        }

        #endregion

        #region IDisposable Members

        /// <summary>
        /// Dispose instances and resources
        /// </summary>
        public void Dispose()
        {
            if (IsConnected)
            {
                Disconnect();
            }

            //cancel thread cluster Object Remome
            DisabledWatcherClusterObjectRemove(500);

            //cancel thread cluster Object add
            DisabledWatcherClusterObjectAdd(500);

            //cancel thread Group State Change
            DisabledWatcherGroupStateChange(500);

            //cancel thread Resource State Change
            DisabledWatcherResourceStateChange(500);

            //dispose internal objects;
            DisposeManagementObjects();

            //clear references
            GroupInstances = null;
            ResourceInstances = null;
            NodeInstances = null;
            NodeInstances = null;
            NetworkInstances = null;
            NetworkInterfaceInstances = null;
            ScopeManager = null;
        }


        #endregion

        #region private Threads

        private void ThreadWatcherResourceStateChange()
        {
            var tmout = new TimeSpan(0, 0, 0, 1);
            var watcher = new ClusterWmiHelpper().GetEventResourceStateChange(ScopeManager);
            while (!_abortThreadResourceStateChange)
            {
                try
                {
                    watcher.Options = new EventWatcherOptions(null, tmout, 1);
                    var resultev = new EventResourceStateChangePropety(watcher.WaitForNextEvent());
                    if (ResourceStateChange != null)
                        ResourceStateChange(this, resultev);
                }
                // ReSharper disable EmptyGeneralCatchClause
                catch
                // ReSharper restore EmptyGeneralCatchClause
                {
                    // timeout
                }
            }
            watcher.Stop();
            watcher.Dispose();
        }

        private void ThreadWatcherGroupStateChange()
        {
            var tmout = new TimeSpan(0, 0, 0, 1);
            var watcher = new ClusterWmiHelpper().GetEventGroupStateChange(ScopeManager);
            while (!_abortThreadGroupStateChange)
            {
                try
                {
                    watcher.Options = new EventWatcherOptions(null, tmout, 1);
                    var resultev = new EventResourceStateChangePropety(watcher.WaitForNextEvent());
                    if (GroupStateChange != null)
                        GroupStateChange(this, resultev);
                }
                // ReSharper disable EmptyGeneralCatchClause
                catch
                // ReSharper restore EmptyGeneralCatchClause
                {
                    // timeout
                }
            }
            watcher.Stop();
            watcher.Dispose();
        }

        private void ThreadWatcherObjectAdd()
        {
            var tmout = new TimeSpan(0, 0, 0, 1);
            var watcher = new ClusterWmiHelpper().GetEventClusterObjectAdd(ScopeManager);
            while (!_abortThreadObjectAdd)
            {
                try
                {
                    watcher.Options = new EventWatcherOptions(null, tmout, 1);
                    var resultev = new EventResourceStateChangePropety(watcher.WaitForNextEvent());
                    if (ClusterObjectAdd != null)
                        ClusterObjectAdd(this, resultev);
                }
                // ReSharper disable EmptyGeneralCatchClause
                catch
                // ReSharper restore EmptyGeneralCatchClause
                {
                    // timeout
                }
            }
            watcher.Stop();
            watcher.Dispose();
        }

        private void ThreadWatcherObjectRemove()
        {
            var tmout = new TimeSpan(0, 0, 0, 1);
            var watcher = new ClusterWmiHelpper().GetEventClusterObjectRemove(ScopeManager);
            while (!_abortThreadObjectRemove)
            {
                try
                {
                    watcher.Options = new EventWatcherOptions(null, tmout, 1);
                    var resultev = new EventResourceStateChangePropety(watcher.WaitForNextEvent());
                    if (ClusterObjectRemove != null)
                        ClusterObjectRemove(this, resultev);
                }
                // ReSharper disable EmptyGeneralCatchClause
                catch
                // ReSharper restore EmptyGeneralCatchClause
                {
                    // timeout
                }
            }
            watcher.Stop();
            watcher.Dispose();
        }

        #endregion
    }

}
